package com.andy.qi.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.andy.qi.conf.RoomServerConf;
import com.andy.qi.domain.GameArchive;
import com.andy.qi.domain.Message;
import com.andy.qi.domain.Room;
import com.andy.qi.domain.User;
import com.andy.qi.repository.GameArchiveRepository;
import com.andy.qi.repository.MessageRepository;
import com.andy.qi.repository.RoomRepository;
import com.andy.qi.repository.UserRepository;
import com.andy.qi.service.EnterInfo;
import com.andy.qi.service.RoomService;
import com.andy.qi.util.StrUtils;

@CrossOrigin(origins = "*")
@RestController
public class ClientController extends WebApi {
    
    @Autowired private UserRepository userRepository;
    @Autowired private RoomRepository roomRepository;
    @Autowired private GameArchiveRepository gameArchiveRepository;
    @Autowired private RoomService roomService;
    @Autowired private MessageRepository messageRepository;
    @Autowired private RoomServerConf config;
    
    @RequestMapping("/login")
    Object login(HttpServletRequest request, String account) {
        User user = userRepository.findOneByAccount(account);
        if(user == null) {
            return succ();
        }
        Map<String, Object> ret = result();
        ret.put("account", user.getAccount());
        ret.put("userid", user.getUserId());
        ret.put("name", user.getName());
        ret.put("lv", user.getLv());
        ret.put("exp", user.getExp());
        ret.put("coins", user.getCoins());
        ret.put("gems", user.getGems());
        ret.put("sex", user.getSex());
        ret.put("ip", ip(request));
        
        if(user.getRoomid() != null) {
            Room room = roomRepository.findOneById(user.getRoomid());
            if(room == null) {
                user.setRoomid(null);
                userRepository.save(user);
            } else {
                ret.put("roomid", user.getRoomid());
            }
        }
        return succ(ret);
    }
    
    @RequestMapping("/create_user")
    Object createUser(String account, String name) {
        User user = userRepository.findOneByAccount(account);
        if(user != null) {
            return fail("account have already exist.");
        }
        int coins = 1000;
        int gems = 21;
        
        user = new User(User.genId(), account);
        user.setName(name);
        user.setCoins(coins);
        user.setGems(gems);
        userRepository.save(user);
        return succ();
    }
    
    @RequestMapping("/create_private_room")
    Object createPrivateRoom(String account, String conf) {
        User user = userRepository.findOneByAccount(account);
        if(user == null) {
            return fail("system error");
        }
        if(user.getRoomid() != null) {
            return reEnter("user is playing in room now.");
        }
        String roomId = roomService.createRoom(account, user.getUserId(), conf);
        if(roomId == null) {
            return fail("create failed.");
        }
        EnterInfo enterInfo = roomService.enterRoom(user.getUserId(), user.getName(), roomId);
        if(enterInfo == null) {
            return fail("enter room fail.");
        }
        return succ(toResult(enterInfo));
    }
    
    @RequestMapping("/enter_private_room")
    Object createPrivateRoom(String roomid, String account, String conf) {
        User user = userRepository.findOneByAccount(account);
        if(user == null) {
            return fail("system error");
        }
        
        EnterInfo enterInfo = roomService.enterRoom(user.getUserId(), user.getName(), roomid);
        if(enterInfo == null) {
            return fail("enter room fail.");
        }
        return succ(toResult(enterInfo));
    }
    
    @RequestMapping("/is_server_online")
    Object isServerOnline(String ip, int port) {
        boolean isonline = roomService.isServerOnline(ip, port);
        Map<String, Object> ret = result();
        ret.put("isonline", isonline);
        return succ(ret);
    }
    
    @RequestMapping("/get_history_list")
    Object getHistoryList(String account) {
        User user = userRepository.findOneByAccount(account);
        if(user == null) {
            return fail("system error");
        }
        Map<String, Object> ret = result();
        ret.put("history", user.getHistory());
        return succ(ret);
    }
    
    @RequestMapping("/get_games_of_room")
    Object getGamesOfRoom(String uuid) {
        List<GameArchive> gameArchives = gameArchiveRepository.findAllByIdRoomUuid(uuid);
        Map<String, Object> ret = result();
        ret.put("data", gameArchives);
        return succ(ret);
    }
    
    @RequestMapping("/get_detail_of_game")
    Object getDetailOfGame(String uuid, int index) {
        GameArchive gameArchive = gameArchiveRepository.findOneByIdRoomUuidAndIdGameIndex(uuid, index);
        Map<String, Object> ret = result();
        ret.put("data", gameArchive);
        return succ(ret);
    }
    
    @RequestMapping("/get_user_status")
    Object getUserStatus(String account) {
        User user = userRepository.findOneByAccount(account);
        if(user == null) {
            return fail("get gems failed.");
        }
        Map<String, Object> ret = result();
        ret.put("gems", user.getGems());
        return succ(ret);
    }
    
    @RequestMapping("/get_message")
    Object getMessage(String type, String version) {
        Message message = messageRepository.findOneByTypeAndVersion(type, version);
        if(message == null) {
            return fail("get message failed.");
        }
        Map<String, Object> ret = result();
        ret.put("msg", message.getMsg());
        ret.put("version", message.getVersion());
        return succ(ret);
    }
    
    
    private Map<String, Object> toResult(EnterInfo enterInfo) {
        long now = System.currentTimeMillis();
        Map<String, Object> ret = result();
        ret.put("roomid", enterInfo.getRoomid());
        ret.put("ip", enterInfo.getIp());
        ret.put("port", enterInfo.getPort());
        ret.put("token", enterInfo.getToken());
        ret.put("time", now);
        ret.put("sign", StrUtils.md5(enterInfo.getRoomid() + enterInfo.getToken() + now + config.getRoomPriKey()));
        return ret;
    }
}